"""
main_window.py

主窗口，提供文件加载、坐标拾取、标注、多边形绘制及尺寸标注功能。
改进：配合 polygon_drawer.py 使用 line.remove() 来卸载线条，避免 'ArtistList' 无 remove 方法的问题。
"""

import os
import sys
import warnings
import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from matplotlib.patches import Rectangle, Polygon
import matplotlib.patheffects as PathEffects
from PyQt5.QtWidgets import (
    QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
    QPushButton, QLabel, QFileDialog, QDialog,
    QTableWidget, QTableWidgetItem, QHeaderView,
    QMessageBox, QStatusBar, QGroupBox, QApplication, QComboBox, QSlider,
    QAction, QMenu, QMenuBar, QSplitter, QTabWidget, QFormLayout, QLineEdit, QTextEdit, QDialogButtonBox, QTabWidget, QScrollArea
)
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QFont, QColor, QIcon
import rasterio
from rasterio.plot import show
from rasterio.warp import calculate_default_transform, reproject, Resampling
import subprocess

# 忽略字体警告
warnings.filterwarnings("ignore", category=UserWarning, module="matplotlib")

# 设置字体路径 - 确保使用fonts文件夹
current_dir = os.path.dirname(os.path.abspath(__file__))
fonts_dir = os.path.join(current_dir, 'fonts')
font_path = os.path.join(fonts_dir, 'kaiti.TTF')

# 添加字体文件
from matplotlib.font_manager import FontProperties, fontManager

# 确保字体文件存在
if os.path.exists(font_path):
    try:
        fontManager.addfont(font_path)
        kaiti_font = FontProperties(fname=font_path)
        print(f"成功加载楷体字体: {font_path}")
    except Exception as e:
        print(f"加载楷体字体失败: {e}")
        # 创建一个默认字体属性
        kaiti_font = FontProperties(family="sans-serif")
else:
    print(f"楷体字体文件不存在: {font_path}")
    # 创建一个默认字体属性
    kaiti_font = FontProperties(family="sans-serif")

# 设置默认字体
matplotlib.rcParams["font.sans-serif"] = ["KaiTi", "SimHei", "SimSun", "Microsoft YaHei", "DejaVu Sans"]
matplotlib.rcParams["axes.unicode_minus"] = False

from image_canvas import ImageCanvas
from orthophoto_utils import (
    read_orthophoto,
    transform_coordinate,
    decimal_degrees_to_dms,
    export_csv
)
from label_manager import LabelManager, LabelDialog
from coordinate_picker import CoordinatePicker
from polygon_drawer import PolygonDrawer  # 多边形绘制模块
from dimension_annotator import DimensionAnnotator  # 尺寸标注模块
from cad_drawer import CADDrawer  # CAD绘图模块
from text_editor import TextEditor, TextEditorDialog  # 文本编辑模块
from distance_calculator import DistanceCalculator  # 距离测量模块

# =========================================================================
# 描述模块对话框类
# =========================================================================
class BuildingDescriptionDialog(QDialog):
    """
    古建筑描述对话框
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("古建筑描述")
        self.setMinimumSize(800, 600)
        self.setup_ui()
        
    def setup_ui(self):
        layout = QVBoxLayout(self)
        
        # 创建选项卡
        tab_widget = QTabWidget()
        
        # 基本信息选项卡
        basic_tab = QWidget()
        basic_layout = QFormLayout(basic_tab)
        
        self.name_edit = QLineEdit()
        basic_layout.addRow("建筑名称:", self.name_edit)
        
        self.location_edit = QLineEdit()
        basic_layout.addRow("位置:", self.location_edit)
        
        self.period_edit = QLineEdit()
        basic_layout.addRow("年代:", self.period_edit)
        
        self.type_edit = QLineEdit()
        basic_layout.addRow("类型:", self.type_edit)
        
        self.size_edit = QLineEdit()
        basic_layout.addRow("规模:", self.size_edit)
        
        # 详细描述选项卡
        detail_tab = QWidget()
        detail_layout = QVBoxLayout(detail_tab)
        
        detail_layout.addWidget(QLabel("建筑详细描述:"))
        self.description_edit = QTextEdit()
        detail_layout.addWidget(self.description_edit)
        
        # 保护状况选项卡
        protection_tab = QWidget()
        protection_layout = QVBoxLayout(protection_tab)
        
        protection_layout.addWidget(QLabel("保护状况:"))
        self.protection_edit = QTextEdit()
        protection_layout.addWidget(self.protection_edit)
        
        # 添加选项卡
        tab_widget.addTab(basic_tab, "基本信息")
        tab_widget.addTab(detail_tab, "详细描述")
        tab_widget.addTab(protection_tab, "保护状况")
        
        layout.addWidget(tab_widget)
        
        # 按钮
        button_box = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.save_description)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
    
    def save_description(self):
        """
        保存描述信息
        """
        try:
            # 获取所有信息
            data = {
                "建筑名称": self.name_edit.text(),
                "位置": self.location_edit.text(),
                "年代": self.period_edit.text(),
                "类型": self.type_edit.text(),
                "规模": self.size_edit.text(),
                "详细描述": self.description_edit.toPlainText(),
                "保护状况": self.protection_edit.toPlainText()
            }
            
            # 保存到文件
            file_path, _ = QFileDialog.getSaveFileName(
                self, "保存古建筑描述", "", "Excel文件 (*.xlsx);;CSV文件 (*.csv);;文本文件 (*.txt)"
            )
            
            if not file_path:
                return
                
            if file_path.endswith('.xlsx'):
                df = pd.DataFrame([data])
                df.to_excel(file_path, index=False)
            elif file_path.endswith('.csv'):
                df = pd.DataFrame([data])
                df.to_csv(file_path, index=False)
            else:
                with open(file_path, 'w', encoding='utf-8') as f:
                    for key, value in data.items():
                        f.write(f"{key}: {value}\n\n")
            
            QMessageBox.information(self, "保存成功", "古建筑描述信息已成功保存！")
            self.accept()
        except Exception as e:
            QMessageBox.warning(self, "保存失败", f"保存古建筑描述信息时出错: {str(e)}")


class SteleDescriptionDialog(QDialog):
    """
    碑刻描述对话框
    """
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("碑刻描述")
        self.setMinimumSize(800, 600)
        self.setup_ui()
        
    def setup_ui(self):
        layout = QVBoxLayout(self)
        
        # 创建选项卡
        tab_widget = QTabWidget()
        
        # 基本信息选项卡
        basic_tab = QWidget()
        basic_layout = QFormLayout(basic_tab)
        
        self.name_edit = QLineEdit()
        basic_layout.addRow("碑刻名称:", self.name_edit)
        
        self.location_edit = QLineEdit()
        basic_layout.addRow("位置:", self.location_edit)
        
        self.period_edit = QLineEdit()
        basic_layout.addRow("年代:", self.period_edit)
        
        self.material_edit = QLineEdit()
        basic_layout.addRow("材质:", self.material_edit)
        
        self.size_edit = QLineEdit()
        basic_layout.addRow("尺寸:", self.size_edit)
        
        self.author_edit = QLineEdit()
        basic_layout.addRow("作者:", self.author_edit)
        
        # 碑文内容选项卡
        content_tab = QWidget()
        content_layout = QVBoxLayout(content_tab)
        
        content_layout.addWidget(QLabel("碑文内容:"))
        self.content_edit = QTextEdit()
        content_layout.addWidget(self.content_edit)
        
        # 保护状况选项卡
        protection_tab = QWidget()
        protection_layout = QVBoxLayout(protection_tab)
        
        protection_layout.addWidget(QLabel("保护状况:"))
        self.protection_edit = QTextEdit()
        protection_layout.addWidget(self.protection_edit)
        
        # 添加选项卡
        tab_widget.addTab(basic_tab, "基本信息")
        tab_widget.addTab(content_tab, "碑文内容")
        tab_widget.addTab(protection_tab, "保护状况")
        
        layout.addWidget(tab_widget)
        
        # 按钮
        button_box = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self.save_description)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)
    
    def save_description(self):
        """
        保存描述信息
        """
        try:
            # 获取所有信息
            data = {
                "碑刻名称": self.name_edit.text(),
                "位置": self.location_edit.text(),
                "年代": self.period_edit.text(),
                "材质": self.material_edit.text(),
                "尺寸": self.size_edit.text(),
                "作者": self.author_edit.text(),
                "碑文内容": self.content_edit.toPlainText(),
                "保护状况": self.protection_edit.toPlainText()
            }
            
            # 保存到文件
            file_path, _ = QFileDialog.getSaveFileName(
                self, "保存碑刻描述", "", "Excel文件 (*.xlsx);;CSV文件 (*.csv);;文本文件 (*.txt)"
            )
            
            if not file_path:
                return
                
            if file_path.endswith('.xlsx'):
                df = pd.DataFrame([data])
                df.to_excel(file_path, index=False)
            elif file_path.endswith('.csv'):
                df = pd.DataFrame([data])
                df.to_csv(file_path, index=False)
            else:
                with open(file_path, 'w', encoding='utf-8') as f:
                    for key, value in data.items():
                        f.write(f"{key}: {value}\n\n")
            
            QMessageBox.information(self, "保存成功", "碑刻描述信息已成功保存！")
            self.accept()
        except Exception as e:
            QMessageBox.warning(self, "保存失败", f"保存碑刻描述信息时出错: {str(e)}")


class MainWindow(QMainWindow):
    """
    主窗口，提供文件加载、坐标拾取、标注、多边形绘制以及尺寸标注功能。
    """
    def __init__(self):
        super().__init__()
        self.setWindowTitle("第四次全国文物普查内业工具包")
        self.resize(1920, 1080)  # 调整窗口初始大小为1920x1080
        
        # 设置窗口图标
        self.setWindowIcon(QIcon("logo.png"))  # 确保 'logo.png' 文件在工作目录下

        # 启用拖放功能
        self.setAcceptDrops(True)

        # 设置窗口背景颜色为淡灰色
        self.setStyleSheet("""
            QMainWindow {
                background-color: #F5F5F5;
            }
            QWidget {
                background-color: #F5F5F5;
            }
            QGroupBox {
                background-color: #F5F5F5;
            }
            QPushButton {
                background-color: #FFFFFF;
                border: 1px solid #CCCCCC;
                border-radius: 3px;
                padding: 5px;
            }
            QPushButton:hover {
                background-color: #E8E8E8;
            }
            QPushButton:pressed {
                background-color: #D3D3D3;
            }
            QTableWidget {
                background-color: #FFFFFF;
                border: 1px solid #CCCCCC;
                gridline-color: #E0E0E0;
            }
            QTableWidget::item {
                padding: 5px;
            }
            QTableWidget::item:selected {
                background-color: #E8E8E8;
            }
            QHeaderView::section {
                background-color: #F0F0F0;
                padding: 5px;
                border: 1px solid #CCCCCC;
            }
            QComboBox {
                background-color: #FFFFFF;
                border: 1px solid #CCCCCC;
                border-radius: 3px;
                padding: 3px;
            }
            QSlider::groove:horizontal {
                border: 1px solid #CCCCCC;
                height: 8px;
                background: #FFFFFF;
            }
            QSlider::handle:horizontal {
                background: #FFFFFF;
                border: 1px solid #CCCCCC;
                width: 18px;
                margin: -2px 0;
                border-radius: 3px;
            }
            QSlider::handle:horizontal:hover {
                background: #E8E8E8;
            }
            QSlider::handle:horizontal:pressed {
                background: #D3D3D3;
            }
        """)

        # DOM / DSM / 变换等数据
        self.dataset_dom = None   # DOM 数据
        self.dataset_dsm = None   # DSM 数据
        self.transform = None
        self.coords_list = []
        self.is_orthophoto = False  # 新增：标记是否为正射影像

        # 创建菜单栏
        self.create_menu_bar()

        # ============ 主 Widget ============
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QHBoxLayout(central_widget)  # 改为水平布局，左侧按钮，右侧内容
        main_layout.setContentsMargins(10, 10, 10, 10)  # 增加边距
        main_layout.setSpacing(10)  # 增加间距

        # 状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)

        # =========================================================================
        # 左侧按钮面板
        # =========================================================================
        left_panel = QWidget()
        left_panel.setMaximumWidth(300)  # 增加左侧面板最大宽度
        left_layout = QVBoxLayout(left_panel)
        left_layout.setSpacing(10)  # 增加各组之间的间距
        left_layout.setContentsMargins(10, 10, 10, 10)  # 增加边距

        # 2. 坐标拾取部分
        coord_group = QGroupBox("坐标拾取")
        coord_layout = QVBoxLayout(coord_group)
        coord_layout.setContentsMargins(5, 5, 5, 5)  # 减小内部边距
        coord_layout.setSpacing(3)  # 减小按钮之间的间距
        
        self.btn_pick_coord = QPushButton("拾取坐标")
        self.btn_pick_coord.clicked.connect(self.toggle_coordinate_pick)
        coord_layout.addWidget(self.btn_pick_coord)
        
        self.btn_clear_coords = QPushButton("清除坐标")
        self.btn_clear_coords.clicked.connect(self.clear_coords)
        coord_layout.addWidget(self.btn_clear_coords)
        
        self.btn_measure_distance = QPushButton("距离测量")
        self.btn_measure_distance.clicked.connect(self.toggle_distance_measure)
        coord_layout.addWidget(self.btn_measure_distance)
        
        self.btn_export_coords = QPushButton("导出坐标")
        self.btn_export_coords.clicked.connect(self.export_coords)
        coord_layout.addWidget(self.btn_export_coords)
        
        left_layout.addWidget(coord_group)
        
        # 3. 标注操作
        annotation_group = QGroupBox("标注操作")
        annotation_layout = QVBoxLayout(annotation_group)
        annotation_layout.setContentsMargins(5, 5, 5, 5)  # 减小内部边距
        annotation_layout.setSpacing(3)  # 减小按钮之间的间距
        
        self.btn_mark = QPushButton("开始标注")
        self.btn_mark.clicked.connect(self.toggle_label_mode)
        annotation_layout.addWidget(self.btn_mark)
        
        self.btn_clear_label = QPushButton("清空标注")
        self.btn_clear_label.clicked.connect(self.clear_label)
        annotation_layout.addWidget(self.btn_clear_label)
        
        self.btn_draw_polygon = QPushButton("绘制虚线图框")
        self.btn_draw_polygon.clicked.connect(self.start_draw_polygon)
        annotation_layout.addWidget(self.btn_draw_polygon)
        
        self.btn_clear_polygon = QPushButton("清空虚线图框")
        self.btn_clear_polygon.clicked.connect(self.clear_polygon)
        annotation_layout.addWidget(self.btn_clear_polygon)
        
        self.btn_export_label = QPushButton("导出标注")
        self.btn_export_label.clicked.connect(self.export_label)
        annotation_layout.addWidget(self.btn_export_label)
        
        left_layout.addWidget(annotation_group)
        
        # 4. CAD绘图
        cad_group = QGroupBox("CAD绘图")
        cad_layout = QVBoxLayout(cad_group)
        cad_layout.setContentsMargins(5, 5, 5, 5)  # 减小内部边距
        cad_layout.setSpacing(3)  # 减小按钮之间的间距
        
        self.btn_draw_line = QPushButton("绘制直线")
        self.btn_draw_line.clicked.connect(self.start_draw_line)
        cad_layout.addWidget(self.btn_draw_line)
        
        self.btn_draw_rectangle = QPushButton("绘制矩形")
        self.btn_draw_rectangle.clicked.connect(self.start_draw_rectangle)
        cad_layout.addWidget(self.btn_draw_rectangle)
        
        self.btn_draw_circle = QPushButton("绘制圆形")
        self.btn_draw_circle.clicked.connect(self.start_draw_circle)
        cad_layout.addWidget(self.btn_draw_circle)
        
        self.btn_edit_rectangle = QPushButton("编辑矩形")
        self.btn_edit_rectangle.clicked.connect(self.start_edit_rectangle)
        cad_layout.addWidget(self.btn_edit_rectangle)
        
        self.btn_erase_line = QPushButton("删除图形")
        self.btn_erase_line.clicked.connect(self.start_erase_line)
        cad_layout.addWidget(self.btn_erase_line)
        
        self.btn_point_coord = QPushButton("点坐标")
        self.btn_point_coord.clicked.connect(self.start_point_coord)
        cad_layout.addWidget(self.btn_point_coord)
        
        # 颜色选择
        color_layout = QHBoxLayout()
        color_layout.addWidget(QLabel("颜色:"))
        self.color_combo = QComboBox()
        self.color_combo.addItems(['蓝色', '红色', '绿色', '黄色', '黑色', '白色'])
        self.color_combo.currentTextChanged.connect(self.change_cad_color)
        color_layout.addWidget(self.color_combo)
        cad_layout.addLayout(color_layout)
        
        # 透明度调整
        alpha_layout = QHBoxLayout()
        alpha_layout.addWidget(QLabel("透明度:"))
        self.alpha_slider = QSlider(Qt.Horizontal)
        self.alpha_slider.setRange(0, 100)
        self.alpha_slider.setValue(100)  # 默认值为100（完全不透明）
        self.alpha_slider.valueChanged.connect(self.change_image_alpha)
        alpha_layout.addWidget(self.alpha_slider)
        cad_layout.addLayout(alpha_layout)
        
        self.btn_clear_cad = QPushButton("清空CAD")
        self.btn_clear_cad.clicked.connect(self.clear_cad)
        cad_layout.addWidget(self.btn_clear_cad)
        
        self.btn_export_cad = QPushButton("导出CAD")
        self.btn_export_cad.clicked.connect(self.export_cad)
        cad_layout.addWidget(self.btn_export_cad)
        
        self.btn_add_text = QPushButton("添加文本")
        self.btn_add_text.clicked.connect(self.start_text_editing)
        cad_layout.addWidget(self.btn_add_text)
        
        self.btn_clear_text = QPushButton("清空文本")
        self.btn_clear_text.clicked.connect(self.clear_text)
        cad_layout.addWidget(self.btn_clear_text)
        
        left_layout.addWidget(cad_group)
        
        # 添加弹性空间
        left_layout.addStretch(1)
        
        # =========================================================================
        # 右侧内容区域
        # =========================================================================
        right_panel = QWidget()
        right_layout = QHBoxLayout(right_panel)  # 改为水平布局，左侧图像，右侧表格
        right_layout.setContentsMargins(10, 10, 10, 10)  # 增加边距
        right_layout.setSpacing(10)  # 增加间距
        
        # 左侧：影像区域
        canvas_widget = QWidget()
        canvas_layout = QVBoxLayout(canvas_widget)
        canvas_layout.setContentsMargins(10, 10, 10, 10)  # 增加边距
        self.canvas = ImageCanvas()
        self.canvas.mpl_connect("button_press_event", self.on_click_image)
        canvas_layout.addWidget(self.canvas)
        canvas_widget.setLayout(canvas_layout)
        
        # 右侧：表格区域
        tables_widget = QWidget()
        tables_widget.setMinimumWidth(1000)  # 增加表格区域最小宽度
        tables_widget.setMaximumWidth(1200)  # 增加表格区域最大宽度
        tables_layout = QVBoxLayout(tables_widget)
        tables_layout.setSpacing(10)  # 增加表格之间的间距
        tables_layout.setContentsMargins(10, 10, 10, 10)  # 增加边距
        
        # 坐标列表
        coords_group = QGroupBox("点选坐标列表")
        coords_layout = QVBoxLayout(coords_group)
        coords_layout.setContentsMargins(3, 3, 3, 3)  # 减小内部边距
        self.table_coords = QTableWidget()
        self.table_coords.setColumnCount(6)
        self.table_coords.setHorizontalHeaderLabels([
            "序号", "测点类型", "纬度", "经度", "海拔高程", "测点说明"
        ])
        self.table_coords.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table_coords.setMinimumHeight(500)  # 增加最小高度
        coords_layout.addWidget(self.table_coords)
        coords_group.setLayout(coords_layout)
        tables_layout.addWidget(coords_group)
        
        # 标注列表
        labels_group = QGroupBox("标注栏")
        labels_layout = QVBoxLayout(labels_group)
        labels_layout.setContentsMargins(3, 3, 3, 3)  # 减小内部边距
        self.table_labels = QTableWidget()
        self.table_labels.setColumnCount(2)
        self.table_labels.setHorizontalHeaderLabels(["标注序号", "内容"])
        self.table_labels.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table_labels.setMinimumHeight(500)  # 增加最小高度
        labels_layout.addWidget(self.table_labels)
        labels_group.setLayout(labels_layout)
        tables_layout.addWidget(labels_group)
        
        # 文本列表
        texts_group = QGroupBox("文本列表")
        texts_layout = QVBoxLayout(texts_group)
        texts_layout.setContentsMargins(3, 3, 3, 3)  # 减小内部边距
        self.table_texts = QTableWidget()
        self.table_texts.setColumnCount(3)
        self.table_texts.setHorizontalHeaderLabels(["文本内容", "字体大小", "颜色"])
        self.table_texts.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table_texts.setMinimumHeight(500)  # 增加最小高度
        texts_layout.addWidget(self.table_texts)
        texts_group.setLayout(texts_layout)
        tables_layout.addWidget(texts_group)
        
        # 添加弹性空间，使表格区域在顶部对齐
        tables_layout.addStretch(1)
        
        # 将图像区域和表格区域添加到右侧面板
        right_layout.addWidget(canvas_widget, 3)  # 图像区域占据更多空间，比例调整为3
        right_layout.addWidget(tables_widget, 1)  # 表格区域占据的空间比例为1
        
        # 将左侧面板和右侧内容区域添加到主布局
        main_layout.addWidget(left_panel)
        main_layout.addWidget(right_panel, 1)  # 右侧区域占据更多空间
        
        # 初始化各种工具
        self.coordinate_picker = CoordinatePicker(
            self.canvas,
            self.table_coords,
            dataset_dom=self.dataset_dom,
            dataset_dsm=self.dataset_dsm
        )
        self.label_manager = LabelManager(self.canvas, self.table_labels)
        self.polygon_drawer = PolygonDrawer(self.canvas)
        self.dimension_annotator = DimensionAnnotator(self.canvas)
        self.cad_drawer = CADDrawer(self.canvas)
        # 设置退出绘图模式的回调函数
        self.cad_drawer.on_exit_drawing_mode = self.reset_all_button_styles
        self.text_editor = TextEditor(self.canvas, self.table_texts)
        self.distance_calculator = DistanceCalculator(self.canvas, self)
        
        # 更新状态栏
        self.update_status("就绪")

    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()
        
        # 文件菜单
        file_menu = menubar.addMenu('文件')
        
        import_action = QAction('导入数据', self)
        import_action.setShortcut('Ctrl+O')
        import_action.triggered.connect(self.unified_import)
        file_menu.addAction(import_action)
        
        import_dom_action = QAction('导入DOM', self)
        import_dom_action.triggered.connect(self.load_tif_dom)
        file_menu.addAction(import_dom_action)
        
        import_dsm_action = QAction('导入DSM', self)
        import_dsm_action.triggered.connect(self.load_tif_dsm)
        file_menu.addAction(import_dsm_action)
        
        import_image_action = QAction('导入图片', self)
        import_image_action.triggered.connect(self.load_image)
        file_menu.addAction(import_image_action)
        
        file_menu.addSeparator()
        
        clear_action = QAction('清空数据', self)
        clear_action.triggered.connect(self.clear_all)
        file_menu.addAction(clear_action)
        
        file_menu.addSeparator()
        
        exit_action = QAction('退出', self)
        exit_action.setShortcut('Ctrl+Q')
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)
        
        # 描述工具菜单
        description_menu = menubar.addMenu('描述工具')
        
        building_action = QAction('古建筑描述', self)
        building_action.triggered.connect(self.open_building_description)
        description_menu.addAction(building_action)
        
        stele_action = QAction('碑刻描述', self)
        stele_action.triggered.connect(self.open_stele_description)
        description_menu.addAction(stele_action)
        
        # 关于菜单
        about_menu = menubar.addMenu('关于')
        
        version_action = QAction('版本信息', self)
        version_action.triggered.connect(self.show_version_info)
        about_menu.addAction(version_action)
        
        # 特别鸣谢
        thanks_action = QAction('特别鸣谢', self)
        thanks_action.triggered.connect(self.show_special_thanks)
        about_menu.addAction(thanks_action)

    # =========================================================================
    #  新增功能
    # =========================================================================
    
    def unified_import(self):
        """
        统一的导入功能，自动识别文件类型（DOM、DSM或普通图片）
        """
        file_path, _ = QFileDialog.getOpenFileName(
            self, 
            "导入数据", 
            "", 
            "所有支持的文件 (*.tif *.tiff *.jpg *.jpeg *.png);;TIF文件 (*.tif *.tiff);;图片文件 (*.jpg *.jpeg *.png)"
        )
        
        if not file_path:
            return
            
        # 获取文件扩展名
        _, ext = os.path.splitext(file_path)
        ext = ext.lower()
        
        try:
            # 如果是TIF文件，尝试作为地理数据打开
            if ext in ['.tif', '.tiff']:
                # 尝试读取为地理数据
                try:
                    dataset, image_array = read_orthophoto(file_path)
                    self.is_orthophoto = True  # 设置为正射影像
                    
                    # 检查是否包含高程数据（DSM）
                    if dataset.count == 1:
                        self.dataset_dsm = dataset
                        self.coordinate_picker.set_dataset_dsm(self.dataset_dsm)
                        QMessageBox.information(self, "提示", "已识别为DSM文件，可获取海拔信息。")
                        
                        if self.dataset_dom:
                            self.update_status(f"已加载DSM: {file_path}")
                        else:
                            self.transform = dataset.transform
                            image_data = image_array.transpose((1, 2, 0))
                            self.canvas.show_image(image_data, self.transform)
                            self.update_status(f"已加载DSM: {file_path}")
                    else:
                        self.dataset_dom = dataset
                        self.transform = dataset.transform
                        image_data = image_array.transpose((1, 2, 0))
                        self.canvas.show_image(image_data, self.transform)
                        self.coordinate_picker.set_dataset_dom(self.dataset_dom)
                        self.update_status(f"已加载DOM: {file_path}")
                except Exception as e:
                    QMessageBox.warning(self, "警告", f"无法作为地理数据打开，将尝试作为普通图片打开: {str(e)}")
                    self.load_as_image(file_path)
            else:
                self.load_as_image(file_path)
            
            # 更新按钮状态
            self.update_buttons_state()
            
        except Exception as e:
            QMessageBox.critical(self, "读取错误", f"无法读取文件：{str(e)}")
    
    def load_as_image(self, file_path):
        """
        作为普通图片加载
        """
        try:
            from PIL import Image
            import numpy as np
            
            # 使用PIL打开图片
            img = Image.open(file_path)
            img_array = np.array(img)
            
            # 显示图片（没有地理坐标信息）
            self.canvas.show_image(img_array, None)
            self.transform = None
            self.is_orthophoto = False  # 设置为非正射影像
            
            # 清除DOM和DSM数据
            if self.dataset_dom:
                self.dataset_dom.close()
                self.dataset_dom = None
            if self.dataset_dsm:
                self.dataset_dsm.close()
                self.dataset_dsm = None
            
            self.update_status(f"已加载图片: {file_path}")
            
        except Exception as e:
            QMessageBox.critical(self, "读取错误", f"无法读取图片文件：{str(e)}")

    def load_image(self):
        """
        导入普通图片（JPG、JPEG、PNG）- 为了兼容现有按钮
        """
        self.unified_import()  # 直接调用统一导入功能

    # =========================================================================
    #  事件与功能函数
    # =========================================================================

    def keyPressEvent(self, event):
        """处理键盘事件"""
        # 处理ESC键
        if event.key() == Qt.Key_Escape:
            # 重置所有按钮样式
            self.reset_all_button_styles()
            self.update_status("就绪")
        else:
            # 调用父类方法处理其他键盘事件
            super().keyPressEvent(event)

    def on_click_image(self, event):
        """
        根据当前状态进行处理：
         1) 若处于坐标拾取模式 => return，让 coordinate_picker 自行处理
         2) 若处于多边形绘制模式 => return，让 polygon_drawer 自行处理
         3) 若处于标注模式 => 弹出标注对话框
         4) 若处于文本编辑模式 => 弹出文本编辑对话框
         5) 其他状态 => 不处理
        """
        # 坐标拾取
        if self.coordinate_picker.is_in_select_mode():
            return
        # 多边形绘制
        if self.polygon_drawer.is_drawing_polygon:
            return
        # 标注模式
        if self.label_manager.is_labeling:
            if not self.dataset_dom:
                return
            if event.inaxes != self.canvas.ax:
                return
            xdata, ydata = event.xdata, event.ydata
            if xdata is None or ydata is None:
                return
            dlg = LabelDialog(self)
            if dlg.exec_() == dlg.Accepted:
                order_str, content_str = dlg.get_data()
                if order_str and content_str:
                    self.label_manager.add_annotation(xdata, ydata, order_str, content_str)
        # 文本编辑模式
        elif self.text_editor.is_text_editing:
            if not self.dataset_dom:
                return
            if event.inaxes != self.canvas.ax:
                return
            xdata, ydata = event.xdata, event.ydata
            if xdata is None or ydata is None:
                return
            dlg = TextEditorDialog(self)
            if dlg.exec_() == dlg.Accepted:
                text_data = dlg.get_text_data()
                if text_data and text_data["text"]:
                    self.text_editor.add_text(xdata, ydata, text_data)

    # =========================================================================
    #  坐标拾取功能
    # =========================================================================

    def toggle_coordinate_pick(self):
        """
        切换坐标拾取模式
        """
        # 如果正在测量距离，先退出测量模式
        if self.distance_calculator.is_in_measure_mode():
            self.distance_calculator.toggle_distance_measure()
            self.btn_measure_distance.setStyleSheet("")
        
        self.coordinate_picker.toggle_coordinate_pick()
        if self.coordinate_picker.is_in_select_mode():
            self.btn_pick_coord.setStyleSheet("background-color: #90EE90")
            self.update_status("坐标拾取模式：点击图像获取坐标")
        else:
            self.btn_pick_coord.setStyleSheet("")
            self.update_status("退出坐标拾取模式")

    def clear_coords(self):
        """
        清空坐标列表
        """
        self.table_coords.setRowCount(0)
        self.coordinate_picker.clear_coords()

    def export_coords(self):
        """
        导出当前拾取的坐标列表到 CSV 文件
        """
        try:
            coords_to_export = self.coordinate_picker.get_coords()
            if not coords_to_export:
                QMessageBox.warning(self, "导出坐标", "当前没有拾取的坐标，无法导出！")
                return
            out_path, _ = QFileDialog.getSaveFileName(self, "导出坐标", "", "CSV Files (*.csv)")
            if not out_path:
                return
            export_csv(coords_to_export, out_path)
            QMessageBox.information(self, "导出成功", f"坐标已成功导出到：{out_path}")
        except Exception as e:
            QMessageBox.critical(self, "导出失败", f"导出坐标时发生错误：{str(e)}")

    # =========================================================================
    #  标注功能
    # =========================================================================

    def toggle_label_mode(self):
        """
        切换标注模式
        """
        if not self.label_manager.is_labeling:
            # 若坐标拾取模式，先关闭
            if self.coordinate_picker.is_in_select_mode():
                self.coordinate_picker.toggle_coordinate_pick()
            # 若多边形绘制模式，先关闭
            if self.polygon_drawer.is_drawing_polygon:
                self.polygon_drawer.stop_polygon_mode()
            self.label_manager.start_labeling()
            QMessageBox.information(self, "提示", "已进入标注模式，点击图像可创建标注。\n按ESC键退出标注模式。")
            self.update_status("标注模式")
        else:
            self.label_manager.stop_labeling()
            QMessageBox.information(self, "提示", "已退出标注模式！")
            self.update_status("")

    def clear_label(self):
        """
        清空所有标注
        """
        self.label_manager.clear_annotations()

    def export_label(self):
        """
        导出带标注的图像
        """
        out_path, _ = QFileDialog.getSaveFileName(self, "导出标注图像", "", "PNG Files (*.png)")
        if out_path:
            self.label_manager.export_labeled_image(out_path)

    # =========================================================================
    #  多边形绘制功能
    # =========================================================================

    def start_draw_polygon(self):
        """
        点击"开始绘制多边形"按钮：
         - 先退出坐标拾取/标注模式，避免冲突
         - 进入多边形绘制模式
        """
        if self.coordinate_picker.is_in_select_mode():
            self.coordinate_picker.toggle_coordinate_pick()
        if self.label_manager.is_labeling:
            self.label_manager.stop_labeling()
        self.polygon_drawer.start_polygon_mode()
        QMessageBox.information(self, "提示", "已进入多边形绘制模式：\n左键依次下顶点，右键或按ESC可结束。")

    def clear_polygon(self):
        """
        清空已绘制的多边形
        注意：在 polygon_drawer 内部使用 line.remove() 卸载线条，避免出现 remove 错误。
        """
        self.polygon_drawer.clear_polygons()
        QMessageBox.information(self, "提示", "已清空多边形。")

    # =========================================================================
    #  尺寸标注功能
    # =========================================================================

    def start_dimension_annotation(self):
        """
        开始尺寸标注模式：
         - 退出坐标拾取、标注和多边形绘制模式（避免冲突）
         - 进入尺寸标注模式，等待用户依次点击两个点进行测距
        """
        if self.coordinate_picker.is_in_select_mode():
            self.coordinate_picker.toggle_coordinate_pick()
        if self.label_manager.is_labeling:
            self.label_manager.stop_labeling()
        if self.polygon_drawer.is_drawing_polygon:
            self.polygon_drawer.stop_polygon_mode()
        self.dimension_annotator.start_dimension_mode()
        self.update_status("尺寸标注模式")

    def clear_dimension_annotation(self):
        """
        清空所有已绘制的尺寸标注
        """
        self.dimension_annotator.clear_annotations()
        QMessageBox.information(self, "提示", "已清空尺寸标注。")

    # =========================================================================
    #  数据加载和清空
    # =========================================================================

    def load_tif_dom(self):
        """
        导入DOM - 为了兼容现有按钮
        """
        self.unified_import()  # 直接调用统一导入功能

    def load_tif_dsm(self):
        """
        导入DSM - 为了兼容现有按钮
        """
        self.unified_import()  # 直接调用统一导入功能

    def clear_all(self):
        """
        清空所有数据
        """
        try:
            # 清空图像数据
            if hasattr(self, 'dataset_dom') and self.dataset_dom is not None:
                self.dataset_dom.close()
                self.dataset_dom = None
            
            if hasattr(self, 'dataset_dsm') and self.dataset_dsm is not None:
                self.dataset_dsm.close()
                self.dataset_dsm = None
            
            # 清空图像
            if hasattr(self, 'ax') and self.ax is not None:
                self.ax.clear()
                self.canvas.draw()
            
            # 清空坐标
            self.clear_coords()
            
            # 清空标注
            self.clear_label()
            
            # 清空多边形
            self.clear_polygon()
            
            # 清空CAD
            self.clear_cad()
            
            # 清空文本
            self.clear_text()
            
            # 清空距离测量
            if hasattr(self, 'distance_calculator'):
                self.distance_calculator.clear_measurement()
            
            # 重置状态
            self.is_picking = False
            self.is_labeling = False
            self.is_measuring = False
            self.is_drawing_polygon = False
            self.is_drawing_line = False
            self.is_drawing_rectangle = False
            self.is_editing_rectangle = False
            self.is_erasing = False
            self.is_adding_point_coord = False
            
            # 更新状态栏
            self.statusBar().showMessage("已清空所有数据")
            
        except Exception as e:
            QMessageBox.warning(self, "错误", f"清空数据时出错: {str(e)}")

    # =========================================================================
    #  版本信息弹窗
    # =========================================================================

    def show_version_info(self):
        """
        显示版本信息
        """
        # 创建一个QDialog
        dialog = QDialog(self)
        dialog.setWindowTitle("版本信息")
        dialog.setMinimumWidth(400)
        
        # 创建布局
        layout = QVBoxLayout(dialog)
        
        # 基本信息
        basic_info = f"""
        <h3>文物普查内业工具包</h3>
        <p>版本：v1.0.1</p>
        <p>更新日期：2024-03-22</p>
        <p>Gitee仓库：https://gitee.com/wahonet/siputools</p>
        <p>开发者：嘉祥县文物保护中心</p>
        """
        
        basic_label = QLabel(basic_info)
        basic_label.setOpenExternalLinks(True)
        layout.addWidget(basic_label)
        
        # 创建一个QTabWidget用于显示更新历史
        tab_widget = QTabWidget()
        
        # 当前版本更新内容
        current_tab = QWidget()
        current_layout = QVBoxLayout(current_tab)
        current_content = """
        <p><b>当前版本更新内容:</b></p>
        <ul>
            <li>新增拖放功能，支持直接拖入正射影像和图片文件</li>
            <li>优化了UI布局，改善了整体界面美观度</li>
            <li>修复了部分按钮状态显示问题</li>
            <li>优化了窗口大小和布局比例</li>
            <li>改进了表格区域的显示效果</li>
        </ul>
        """
        current_label = QLabel(current_content)
        current_layout.addWidget(current_label)
        tab_widget.addTab(current_tab, "当前版本")
        
        # 历史更新内容
        history_tab = QWidget()
        history_layout = QVBoxLayout(history_tab)
        history_content = """
        <p>Ver 1.0.1</p>
        <ul>
            <li>新增拖放功能，支持直接拖入正射影像和图片文件</li>
            <li>优化了UI布局，改善了整体界面美观度</li>
            <li>修复了部分按钮状态显示问题</li>
            <li>优化了窗口大小和布局比例</li>
            <li>改进了表格区域的显示效果</li>
        </ul>
        <p>Ver 1.0.0</p>
        <ul>
            <li>优化了UI布局，改善了整体界面美观度</li>
            <li>修复了部分按钮状态显示问题</li>
            <li>优化了窗口大小和布局比例</li>
            <li>改进了表格区域的显示效果</li>
        </ul>
        <p>Ver 0.94</p>
        <ul>
            <li>文本可随CAD一起导出，便于制作完整图纸</li>
            <li>增加正射影像透明度调整功能，便于描图</li>
            <li>统一导入功能，自动识别文件类型</li>
        </ul>
        <p>Ver 0.93</p>
        <ul>
            <li>增强文本编辑功能，支持系统中所有可用字体</li>
            <li>优化字体显示效果，提高中文字体兼容性</li>
        </ul>
        <p>Ver 0.92</p>
        <ul>
            <li>新增文本编辑功能，支持添加可调整大小和颜色的文本</li>
            <li>优化了界面布局，提高了用户体验</li>
        </ul>
        <p>Ver 0.91</p>
        <ul>
            <li>修复了导出图像时可能出现的"cannot remove artist"错误</li>
            <li>优化了图像加载和清除功能，提高了稳定性</li>
        </ul>
        <p>Ver 0.90</p>
        <ul>
            <li>调整了按钮布局，优化了用户界面</li>
            <li>增加了CAD绘图功能</li>
            <li>修复了一些已知问题</li>
        </ul>
        <p>Ver 0.80</p>
        <ul>
            <li>优化了影像显示功能，保持正确的宽高比</li>
            <li>提升了影像显示性能</li>
        </ul>
        <p>Ver 0.70</p>
        <ul>
            <li>增加古建筑描述模块</li>
            <li>增加碑刻描述模块</li>
        </ul>
        <p>Ver 0.60</p>
        <ul>
            <li>优化了UI布局</li>
            <li>增加了根据正射影像进行尺寸标注的功能</li>
            <li>增加了根据正射影像进行坐标拾取的功能</li>
            <li>增加了根据正射影像进行多边形绘制的功能</li>
            <li>增加了根据正射影像进行标注的功能</li>
        </ul>
        """
        history_scroll = QScrollArea()
        history_content_widget = QWidget()
        history_content_layout = QVBoxLayout(history_content_widget)
        history_label = QLabel(history_content)
        history_content_layout.addWidget(history_label)
        history_content_layout.addStretch()
        history_scroll.setWidget(history_content_widget)
        history_scroll.setWidgetResizable(True)
        history_layout.addWidget(history_scroll)
        tab_widget.addTab(history_tab, "历史版本")
        
        layout.addWidget(tab_widget)
        
        # 版权信息
        copyright_label = QLabel("<p>版权所有……版权所有？没什么版权，完全开源，随意复制</p>")
        layout.addWidget(copyright_label)
        
        # 确定按钮
        button_box = QDialogButtonBox(QDialogButtonBox.Ok)
        button_box.accepted.connect(dialog.accept)
        layout.addWidget(button_box)
        
        dialog.exec_()

    def show_special_thanks(self):
        """
        显示特别鸣谢
        """
        msg = """
        <h3>特别鸣谢</h3>
        <p>特别感谢以下技术支持：</p>
        <ul>
            <li>Cursor</li>
            <li>claude-3.7-sonnet</li>
            <li>Chatgpt 4.0</li>
        </ul>
        <p>赞美科技，赞美AI，为本项目提供的强大技术支持！</p>
        """
        QMessageBox.about(self, "特别鸣谢", msg)

    def open_building_description(self):
        """
        打开古建筑描述对话框
        """
        try:
            # 获取当前程序所在目录
            current_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
            # 在开发环境和打包环境下都能正确找到执行文件
            if getattr(sys, 'frozen', False):
                # 打包环境
                exe_path = os.path.join(current_dir, "building_description.exe")
            else:
                # 开发环境
                exe_path = os.path.join(current_dir, "building_description.py")
                exe_path = [sys.executable, exe_path]
            
            if isinstance(exe_path, list):
                subprocess.Popen(exe_path)
            else:
                subprocess.Popen([exe_path])
        except Exception as e:
            QMessageBox.warning(self, "错误", f"打开古建筑描述模块时出错: {str(e)}")
    
    def open_stele_description(self):
        """
        打开碑刻描述对话框
        """
        try:
            # 获取当前程序所在目录
            current_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
            # 在开发环境和打包环境下都能正确找到执行文件
            if getattr(sys, 'frozen', False):
                # 打包环境
                exe_path = os.path.join(current_dir, "stele_description.exe")
            else:
                # 开发环境
                exe_path = os.path.join(current_dir, "stele_description.py")
                exe_path = [sys.executable, exe_path]
            
            if isinstance(exe_path, list):
                subprocess.Popen(exe_path)
            else:
                subprocess.Popen([exe_path])
        except Exception as e:
            QMessageBox.warning(self, "错误", f"打开碑刻描述模块时出错: {str(e)}")

    def start_draw_line(self):
        """开始直线绘制模式"""
        # 退出其他模式并重置按钮样式
        self.reset_all_button_styles()
        
        # 启动直线绘制模式
        self.cad_drawer.start_line_mode()
        self.btn_draw_line.setStyleSheet("background-color: #90EE90")  # 设置为绿色
        self.update_status("已进入直线绘制模式，点击两次生成直线，按ESC退出")

    def start_draw_rectangle(self):
        """开始矩形绘制模式"""
        # 退出其他模式并重置按钮样式
        self.reset_all_button_styles()
        
        # 启动矩形绘制模式
        self.cad_drawer.start_rectangle_mode()
        self.btn_draw_rectangle.setStyleSheet("background-color: #90EE90")  # 设置为绿色
        self.update_status("已进入矩形绘制模式，点击两次确定对角线，按ESC退出")

    def start_edit_rectangle(self):
        """开始编辑矩形模式"""
        # 退出其他模式并重置按钮样式
        self.reset_all_button_styles()
        
        # 启动编辑矩形模式
        self.cad_drawer.start_edit_rectangle_mode()
        self.btn_edit_rectangle.setStyleSheet("background-color: #90EE90")  # 设置为绿色
        self.update_status("已进入矩形编辑模式，点击要编辑的矩形，按ESC退出")

    def start_erase_line(self):
        """开始删除图形模式"""
        # 退出其他模式并重置按钮样式
        self.reset_all_button_styles()
        
        # 启动删除图形模式
        self.cad_drawer.start_erase_mode()
        self.btn_erase_line.setStyleSheet("background-color: #90EE90")  # 设置为绿色
        self.update_status("已进入删除模式，点击要删除的图形，按ESC退出")

    def start_point_coord(self):
        """开始点坐标模式"""
        # 退出其他模式并重置按钮样式
        self.reset_all_button_styles()
        
        # 启动点坐标模式
        self.cad_drawer.start_point_coord_mode()
        self.btn_point_coord.setStyleSheet("background-color: #90EE90")  # 设置为绿色
        self.update_status("已进入点坐标模式，点击任意位置显示坐标，按ESC退出")

    def reset_all_button_styles(self):
        """重置所有按钮样式"""
        # 退出其他模式
        if self.coordinate_picker.is_in_select_mode():
            self.coordinate_picker.toggle_coordinate_pick()
            self.btn_pick_coord.setStyleSheet("")
        if self.label_manager.is_labeling:
            self.label_manager.stop_labeling()
            self.btn_mark.setStyleSheet("")
        if self.polygon_drawer.is_drawing_polygon:
            self.polygon_drawer.stop_polygon_mode()
            self.btn_draw_polygon.setStyleSheet("")
        if self.dimension_annotator.active:
            self.dimension_annotator.stop_dimension_mode()
        if hasattr(self, 'text_editor') and self.text_editor.is_text_editing:
            self.text_editor.stop_text_editing()
            self.btn_add_text.setStyleSheet("")
        if self.distance_calculator.is_in_measure_mode():
            self.distance_calculator.toggle_distance_measure()
            self.btn_measure_distance.setStyleSheet("")
        
        # 停止CAD绘图模式
        if self.cad_drawer.is_drawing:
            self.cad_drawer.stop_drawing()
        
        # 重置CAD按钮样式
        self.btn_draw_line.setStyleSheet("")
        self.btn_draw_rectangle.setStyleSheet("")
        self.btn_draw_circle.setStyleSheet("")
        self.btn_edit_rectangle.setStyleSheet("")
        self.btn_erase_line.setStyleSheet("")
        self.btn_point_coord.setStyleSheet("")

    def clear_cad(self):
        """清空CAD图层"""
        self.cad_drawer.clear_shapes()
        self.update_status("已清空CAD图层")
        
    def export_cad(self):
        """导出CAD图层"""
        file_path, _ = QFileDialog.getSaveFileName(
            self,
            "导出CAD图层",
            "",
            "PNG文件 (*.png)"
        )
        if file_path:
            # 获取文本编辑器中的文本对象
            text_objects = self.text_editor.text_objects if hasattr(self, 'text_editor') else None
            # 将文本对象传递给CAD导出函数
            self.cad_drawer.export_cad_layer(file_path, text_objects)
            self.update_status(f"CAD图层已导出至: {file_path}")

    def change_cad_color(self, color_name):
        """更改CAD绘图颜色"""
        self.cad_drawer.set_color(color_name)
        self.update_status(f"已切换CAD绘图颜色为: {color_name}")

    def start_text_editing(self):
        """开始文本编辑模式"""
        # 退出其他模式
        if self.coordinate_picker.is_in_select_mode():
            self.coordinate_picker.toggle_coordinate_pick()
        if self.label_manager.is_labeling:
            self.label_manager.stop_labeling()
        if self.polygon_drawer.is_drawing_polygon:
            self.polygon_drawer.stop_polygon_mode()
        if self.dimension_annotator.active:
            self.dimension_annotator.stop_dimension_mode()
        if self.cad_drawer.is_drawing:
            self.cad_drawer.stop_drawing()
            
        # 进入文本编辑模式
        self.text_editor.start_text_editing()
        QMessageBox.information(self, "提示", "已进入文本编辑模式，点击图像添加文本。\n按ESC键退出文本编辑模式。")
        self.update_status("文本编辑模式")

    def clear_text(self):
        """清空文本"""
        self.text_editor.clear_texts()
        QMessageBox.information(self, "提示", "已清空所有文本。")

    def toggle_distance_measure(self):
        """
        切换距离测量模式
        """
        # 如果正在拾取坐标，先关闭坐标拾取
        if self.coordinate_picker.is_in_select_mode():
            self.coordinate_picker.toggle_coordinate_pick()
            self.btn_measure_distance.setStyleSheet("")
        
        self.distance_calculator.toggle_distance_measure()
        
        # 更新按钮样式
        if self.distance_calculator.is_in_measure_mode():
            self.btn_measure_distance.setStyleSheet("background-color: #90EE90;")  # 浅绿色
            self.statusBar().showMessage("距离测量模式：点击两点进行测量")
        else:
            self.btn_measure_distance.setStyleSheet("")
            self.statusBar().showMessage("退出距离测量模式")

    def start_draw_circle(self):
        """开始圆形绘制模式"""
        # 退出其他模式并重置按钮样式
        self.reset_all_button_styles()
        
        # 启动圆形绘制模式
        self.cad_drawer.start_circle_mode()
        self.btn_draw_circle.setStyleSheet("background-color: #90EE90")  # 设置为绿色
        self.update_status("已进入圆形绘制模式，点击确定圆心，拖动确定半径，按ESC退出")

    # =========================================================================
    #  辅助
    # =========================================================================

    def update_status(self, message):
        """
        更新状态栏信息
        """
        self.status_bar.showMessage(message)

    def change_image_alpha(self):
        """更改图像透明度"""
        alpha = self.alpha_slider.value()
        self.canvas.set_alpha(alpha / 100.0)
        self.update_status(f"已设置图像透明度为: {alpha}%")

    def update_buttons_state(self):
        """
        更新按钮状态
        """
        # 需要正射影像的按钮列表
        orthophoto_buttons = [
            self.btn_pick_coord,
            self.btn_clear_coords,
            self.btn_measure_distance,
            self.btn_export_coords,
            self.btn_point_coord
        ]
        
        # 根据是否为正射影像设置按钮状态
        for btn in orthophoto_buttons:
            if self.is_orthophoto:
                btn.setEnabled(True)
                btn.setStyleSheet("")
            else:
                btn.setEnabled(False)
                btn.setStyleSheet("background-color: #D3D3D3;")  # 灰色

    def dragEnterEvent(self, event):
        """
        处理拖入事件
        """
        if event.mimeData().hasUrls():
            event.acceptProposedAction()

    def dropEvent(self, event):
        """
        处理放下事件
        """
        urls = event.mimeData().urls()
        if urls:
            file_path = urls[0].toLocalFile()
            if os.path.isfile(file_path):
                # 获取文件扩展名
                _, ext = os.path.splitext(file_path)
                ext = ext.lower()
                
                # 检查文件类型
                if ext in ['.tif', '.tiff', '.jpg', '.jpeg', '.png']:
                    try:
                        # 如果是TIF文件，尝试作为地理数据打开
                        if ext in ['.tif', '.tiff']:
                            try:
                                dataset, image_array = read_orthophoto(file_path)
                                self.is_orthophoto = True  # 设置为正射影像
                                
                                # 检查是否包含高程数据（DSM）
                                if dataset.count == 1:
                                    self.dataset_dsm = dataset
                                    self.coordinate_picker.set_dataset_dsm(self.dataset_dsm)
                                    QMessageBox.information(self, "提示", "已识别为DSM文件，可获取海拔信息。")
                                    
                                    if self.dataset_dom:
                                        self.update_status(f"已加载DSM: {file_path}")
                                    else:
                                        self.transform = dataset.transform
                                        image_data = image_array.transpose((1, 2, 0))
                                        self.canvas.show_image(image_data, self.transform)
                                        self.update_status(f"已加载DSM: {file_path}")
                                else:
                                    self.dataset_dom = dataset
                                    self.transform = dataset.transform
                                    image_data = image_array.transpose((1, 2, 0))
                                    self.canvas.show_image(image_data, self.transform)
                                    self.coordinate_picker.set_dataset_dom(self.dataset_dom)
                                    self.update_status(f"已加载DOM: {file_path}")
                            except Exception as e:
                                QMessageBox.warning(self, "警告", f"无法作为地理数据打开，将尝试作为普通图片打开: {str(e)}")
                                self.load_as_image(file_path)
                        else:
                            self.load_as_image(file_path)
                        
                        # 更新按钮状态
                        self.update_buttons_state()
                        
                    except Exception as e:
                        QMessageBox.critical(self, "读取错误", f"无法读取文件：{str(e)}")
                else:
                    QMessageBox.warning(self, "警告", "不支持的文件类型，请拖入图片文件（.tif, .tiff, .jpg, .jpeg, .png）")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    main_win = MainWindow()
    main_win.show()
    sys.exit(app.exec_())